﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using winAppGame.model;
using winAppGame.service;

namespace winAppGame
{
    /// <summary>
    /// author:zuowenjun
    /// copyright:www.zuowenjun.cn
    /// 游戏界面
    /// </summary>
    public partial class FormGrame : Form
    {
        private DDZGameService gameService = null;

        private IEnumerable<Pai> lastShowPais = null;
        private PaiRuleType.PaiRuleTypeItem lastShowPaiRuleType = null;
        private Dictionary<object, Pai> lastSelectedPais = new Dictionary<object, Pai>();

        private List<Panel> paiPanels = new List<Panel>();
        private Panel currentPaiPanel = null;
        private Panel lastShowPaiPanel = null;
        private int manualPaiPanelIndex = 0;
        public FormGrame()
        {
            InitializeComponent();
            gameService = new DDZGameService();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            var personPais = gameService.FenPais();
            ShowPais(personPais.Item1, 1);
            ShowPais(personPais.Item2, 2);
            ShowPais(personPais.Item3, 3);

            paiPanels.Clear();
            paiPanels.Add(panel1);
            paiPanels.Add(panel2);
            paiPanels.Add(panel3);

            panel1.Tag = buttonPass1;
            panel2.Tag = buttonPass2;
            panel3.Tag = buttonPass3;

            SetCurrentPaiPanel(null);
            ShowPaiTip("请开始出牌吧！", true);
        }

        private Label BuildPaiLabel(Pai p)
        {
            var paiLabel = new Label();
            string paiKindPic = BaseUtils.GetEnumDescription(p.Kind);
            paiLabel.Text = string.Format("{0}\r\n {1}", p.Name, paiKindPic);
            paiLabel.Font = new Font(new FontFamily("Arial"), 14F, FontStyle.Bold);
            paiLabel.Name = $"pai_{p.Name}_{p.Kind}";
            paiLabel.AutoSize = false;
            paiLabel.Margin = new Padding(5);
            paiLabel.Width = 100;
            paiLabel.Height = 80;
            switch (p.Kind)
            {
                case PaiKind.HongTao:
                    {
                        paiLabel.ForeColor = Color.Red;
                        break;
                    }
                case PaiKind.HeiTao:
                    {
                        paiLabel.ForeColor = Color.Black;
                        break;
                    }
                case PaiKind.MeiHua:
                    {
                        paiLabel.ForeColor = Color.Black;
                        break;
                    }
                case PaiKind.FangKuai:
                    {
                        paiLabel.ForeColor = Color.Red;
                        break;
                    }
            }
            paiLabel.Tag = p;
            paiLabel.Visible = true;
            paiLabel.BorderStyle = BorderStyle.FixedSingle;
            paiLabel.MouseClick += PaiLabel_MouseClick;
            return paiLabel;
        }



        private void PaiLabel_MouseClick(object sender, MouseEventArgs e)
        {
            var currentPai = sender as Label;
            if (currentPaiPanel != currentPai.Parent)
            {
                return;
            }

            if (e.Button == MouseButtons.Left)
            {
                if (lastSelectedPais.HasItem() && lastSelectedPais.ContainsKey(currentPai))
                {
                    currentPai.BackColor = Color.Transparent;
                    lastSelectedPais.Remove(currentPai);
                    return;
                }

                currentPai.BackColor = Color.Orange;
                lastSelectedPais[currentPai] = currentPai.Tag as Pai;
                return;
            }

            if (e.Button == MouseButtons.Right)
            {
                var checkResult = gameService.CheckPais(lastSelectedPais.Values, lastShowPais, lastShowPaiRuleType);
                if (!checkResult.AllowShow)
                {
                    MessageBox.Show(checkResult.ErrMsg, "出牌错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                lastShowPaiPanel = currentPai.Parent as Panel;

                ShowThrow(checkResult, lastSelectedPais);

                if (lastShowPaiPanel.Controls.Cast<Control>().Where(c => c is Label && c.Name.StartsWith("pai_")).Count() <= 0)
                {
                    ShowPaiTip("WIN 率先完成出牌，胜利！", true, true);
                    (lastShowPaiPanel.Tag as Button).Enabled = false;
                }
                else
                {
                    ShowPaiTip(checkResult.RuleType.Name, true);
                }

                lastShowPais = lastSelectedPais.Values.Select(p => p).ToList();
                lastShowPaiRuleType = checkResult.RuleType;
                lastSelectedPais.Clear();
                SetCurrentPaiPanel(currentPaiPanel);
            }

        }

        private void ShowPaiTip(string msg, bool isOk, bool isWin = false)
        {
            string player = null;
            if (currentPaiPanel == panel1)
            {
                player = labelPlayer1.Text;
            }
            else if (currentPaiPanel == panel2)
            {
                player = labelPlayer2.Text;
            }
            else
            {
                player = labelPlayer3.Text;
            }

            labelShowTip.Text = $"{player}=> {msg}";
            if (isOk)
            {
                labelShowTip.ForeColor = Color.Green;
            }
            else
            {
                labelShowTip.ForeColor = Color.Red;
            }

            if (isWin)
            {
                labelShowTip.ForeColor = Color.Yellow;
                labelShowTip.BackColor = Color.Red;
            }

        }

        /// <summary>
        /// 显示抛出的牌
        /// </summary>
        /// <param name="checkResult"></param>
        /// <param name="selectedPais"></param>
        private void ShowThrow(PaiRuleCheckResult checkResult, Dictionary<object, Pai> selectedPais)
        {
            panelShow.Controls.Clear();
            int paiIndex = 0;
            foreach (var obj in selectedPais.Keys)
            {
                var paiLabel = obj as Label;
                var paiLabelParent = paiLabel.Parent;
                paiLabel.Location = new Point(0, 30 * paiIndex);
                paiLabel.MouseClick -= PaiLabel_MouseClick;
                paiLabel.Parent.Controls.Remove(paiLabel);

                MovePaiLabels(paiLabelParent);

                panelShow.Controls.Add(paiLabel);
                paiLabel.BringToFront();
                paiIndex++;
            }
        }

        /// <summary>
        /// 整体移动牌label
        /// </summary>
        /// <param name="paiLabel"></param>
        private void MovePaiLabels(Control paiLabelParent)
        {
            var paiLabels = paiLabelParent.Controls.Cast<Control>().Where(c => c is Label && c.Name.StartsWith("pai_")).OrderBy(c => (Pai)c.Tag).ToList();
            int paiIndex = 0;
            paiLabelParent.Controls.Clear();
            paiLabelParent.Invalidate(true);
            paiLabelParent.Update();
            //paiLabels.ForEach(c => c.Visible = false);

            foreach (var paiLabel in paiLabels)
            {
                if (paiLabelParent == panel1)
                {
                    paiLabel.Left = 30 * paiIndex;
                }
                else
                {
                    paiLabel.Top = 30 * paiIndex;
                }
                paiLabelParent.Controls.Add(paiLabel);
                paiLabel.Visible = true;
                paiLabel.BringToFront();
                paiIndex++;
            }

        }

        private void SetCurrentPaiPanel(Panel current)
        {
            int index = 0;
            if (current != null)
            {
                index = paiPanels.IndexOf(current) + 1;
            }

            if (paiPanels.Count - 1 < index)
            {
                index = 0;
            }
            currentPaiPanel = paiPanels[index];

            for (int i = 0; i < paiPanels.Count; i++)
            {
                Button btn = (paiPanels[i].Tag as Button);
                if (i != index || currentPaiPanel == lastShowPaiPanel)
                {
                    btn.Enabled = false;
                }
                else
                {
                    btn.Enabled = true;
                }
            }

            if (lastShowPaiPanel == null)
            {
                (currentPaiPanel.Tag as Button).Enabled = false;
            }

            //如果自己出牌后，一轮又回到自己（即：其余人都是要不起），则允许重新自定义出牌
            if (currentPaiPanel == lastShowPaiPanel)
            {
                lastShowPaiRuleType = null;
                lastShowPais = null;
            }

            if (currentPaiPanel != paiPanels[manualPaiPanelIndex])
            {
                //如果不是人工发牌时间，则启用延时自动执行电脑出牌
                SetTimeOut(2000, () =>
                {
                    AutoShowPais();
                });
            }
        }

        private void AutoShowPais()
        {
            if (currentPaiPanel == paiPanels[manualPaiPanelIndex])
            {
                return;
            }

            var currentPaiLabels = currentPaiPanel.Controls.Cast<Control>().Where(c => c is Label && c.Name.StartsWith("pai_")).ToList();
            var currentPais = currentPaiLabels.Select(l => l.Tag as Pai);
            var paiSelectedResult = gameService.AutoSelectPais(currentPais, lastShowPais, lastShowPaiRuleType);
            if (paiSelectedResult.AllowShow)
            {
                Dictionary<object, Pai> selectedPais = new Dictionary<object, Pai>();
                Control paiLabel = null;
                foreach (Control paiCtrl in currentPaiLabels)
                {
                    Pai pai = paiCtrl.Tag as Pai;
                    if (paiSelectedResult.ShowPais.ContainsKey(pai) && paiSelectedResult.ShowPais[pai] > selectedPais.Values.Count(p => p == pai))
                    {
                        selectedPais[paiCtrl] = pai;
                        if (paiLabel == null)
                        {
                            paiLabel = paiCtrl;
                        }
                    }
                }

                lastSelectedPais = selectedPais;
                PaiLabel_MouseClick(paiLabel, new MouseEventArgs(MouseButtons.Right, 1, 1, 1, 0));
                //ShowThrow(paiSelectedResult, selectedPais);
            }
            else
            {
                ShowPaiTip("要不起！", false);
                SetCurrentPaiPanel(currentPaiPanel);
            }

        }


        private void ShowPais(List<Pai> pais, int personIndex)
        {
            int paiIndex = 0;
            int offset = 30;
            foreach (var p in pais)
            {
                var paiLabel = BuildPaiLabel(p);
                //this.Controls.Add(paiLabel);

                switch (personIndex)
                {
                    case 1:
                        {
                            paiLabel.Height = panel1.Height;
                            //paiLabel.Left = offset * paiIndex;
                            paiLabel.Location = new Point(offset * paiIndex, 0);
                            panel1.Controls.Add(paiLabel);
                            paiLabel.Parent = panel1;
                            break;
                        }
                    case 2:
                        {
                            paiLabel.Width = panel2.Width;
                            //paiLabel.Top= offset * paiIndex;
                            paiLabel.Location = new Point(0, offset * paiIndex);
                            panel2.Controls.Add(paiLabel);
                            paiLabel.Parent = panel2;
                            break;
                        }
                    default:
                        {
                            paiLabel.Width = panel3.Width;
                            //paiLabel.Top = offset * paiIndex;
                            paiLabel.Location = new Point(0, offset * paiIndex);
                            panel3.Controls.Add(paiLabel);
                            paiLabel.Parent = panel3;
                            break;
                        }
                }
                paiLabel.TabIndex = paiIndex;
                paiLabel.BringToFront();
                paiIndex++;
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            manualPaiPanelIndex = comboBox1.SelectedIndex;
        }

        private void labelPlayer2_Click(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void FormGrame_Shown(object sender, EventArgs e)
        {

        }

        private void buttonPass_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;

            if (lastSelectedPais != null)
            {
                //如果有选中牌，但实际又点“要不起”，则选择牌样式还原
                var keys = lastSelectedPais.Keys.ToArray();
                foreach (var selectedPai in keys)
                {
                    (selectedPai as Label).BackColor = Color.Transparent;
                    lastSelectedPais.Remove(selectedPai);
                }
            }
            ShowPaiTip("要不起！", false);
            SetCurrentPaiPanel(currentPaiPanel);
        }

        private void btnTest_Click(object sender, EventArgs e)
        {
            PaiRuleType.Items();
        }


        private void SetTimeOut(int ms, Action timeOutFunc)
        {
            var timeOutTimer = new System.Timers.Timer();
            timeOutTimer.Interval = ms;
            timeOutTimer.Start();
            timeOutTimer.Elapsed += (s, e) =>
            {
                timeOutTimer.Stop();
                this.BeginInvoke(new Action(() =>
                {
                    timeOutFunc.Invoke();
                }));

            };
        }


    }
}
